<script setup lang="tsx">
import { computed, onMounted, ref, watch } from 'vue';
import { $t } from '@/locales';
import type { Crontab } from '@/service/api';
import CrontabSecond from './tabs/second.vue';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
import CrontabResult from './tabs/result.vue';
import CrontabMin from './tabs/min.vue';
import CrontabHour from './tabs/hour.vue';
import CrontabDay from './tabs/day.vue';
import CrontabMonth from './tabs/month.vue';
import CrontabWeek from './tabs/week.vue';
import CrontabYear from './tabs/year.vue';

defineOptions({
  name: 'CronModel'
});

interface Props {
  expression: string;
}

const props = defineProps<Props>();

interface Emits {
  (e: 'fill'): void;
}

const emit = defineEmits<Emits>();

const visible = defineModel<boolean>('visible', {
  default: false
});
const title = $t('common.job.cronExpressionGenerator');

const tabTitles = [
  $t('common.job.second'),
  $t('common.job.minute'),
  $t('common.job.hour'),
  $t('common.job.day'),
  $t('common.job.month'),
  $t('common.job.week'),
  $t('common.job.year')
];

const crontabValueObj = ref<Crontab>({
  second: '*',
  min: '*',
  hour: '*',
  day: '*',
  month: '*',
  week: '?',
  year: ''
});

const crontabValueString = computed(() => {
  const obj = crontabValueObj;
  const str = `${obj.value.second} ${obj.value.min} ${obj.value.hour} ${obj.value.day} ${obj.value.month} ${
    obj.value.week
  }${obj.value.year === '' ? '' : ` ${obj.value.year}`}`;
  return str;
});

onMounted(() => {
  resolveExp();
});

watch(
  () => props.expression,
  () => {
    resolveExp();
  }
);

function closeDrawer() {
  visible.value = false;
}

function resolveExp() {
  // 反解析 表达式
  if (props.expression) {
    const arr = props.expression.split(' ');
    if (arr.length >= 6) {
      // 6 位以上是合法表达式
      const obj = {
        second: arr[0],
        min: arr[1],
        hour: arr[2],
        day: arr[3],
        month: arr[4],
        week: arr[5],
        year: arr[6] ? arr[6] : ''
      };
      crontabValueObj.value = {
        ...obj
      };
      // Object.entries(obj).forEach(([k, v]) => {
      //   if (v) {
      //     changeRadio(k, v);
      //   }
      // });
    }
  } else {
    // 没有传入的表达式 则还原
    clearCron();
  }
}

// 由子组件触发，更改表达式组成的字段值
const updateCrontabValue = (name: string = '', value: string = '') => {
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-expect-error
  crontabValueObj.value[name] = value;
};

// 表单选项的子组件校验数字格式（通过-props传递）
function checkNumber(value: number, minLimit: number, maxLimit: number) {
  // 检查必须为整数
  let newValue = Math.floor(Number(value));
  if (newValue < minLimit) {
    newValue = minLimit;
  } else if (newValue > maxLimit) {
    newValue = maxLimit;
  }
  return newValue;
}

// 填充表达式
function submitFill() {
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-expect-error
  emit('fill', crontabValueString as string);
  closeDrawer();
}

function clearCron() {
  // 还原选择项
  $t('common.job.preparationForReduction');
  crontabValueObj.value = {
    second: '*',
    min: '*',
    hour: '*',
    day: '*',
    month: '*',
    week: '?',
    year: ''
  };
  // Object.entries(crontabValueObj.value).forEach(([k, v]) => {
  //   if (v) {
  //     changeRadio(k, v);
  //   }
  // });
}
</script>

<template>
  <div>
    <NModal v-model:show="visible" :title="title" preset="card" class="w-250">
      <NScrollbar class="h-250 pr-20px">
        <!-- 表达式 -->
        <NCard>
          <NTabs type="card" animated>
            <NTabPane name="second" :tab="$t('common.job.second')">
              <CrontabSecond class="ml-2" :cron="crontabValueObj" :check="checkNumber" @update="updateCrontabValue" />
            </NTabPane>
            <NTabPane name="minute" :tab="$t('common.job.minute')">
              <CrontabMin class="ml-2" :cron="crontabValueObj" :check="checkNumber" @update="updateCrontabValue" />
            </NTabPane>
            <NTabPane name="hour" :tab="$t('common.job.hour')">
              <CrontabHour class="ml-2" :cron="crontabValueObj" :check="checkNumber" @update="updateCrontabValue" />
            </NTabPane>
            <NTabPane name="day" :tab="$t('common.job.day')">
              <CrontabDay class="ml-2" :cron="crontabValueObj" :check="checkNumber" @update="updateCrontabValue" />
            </NTabPane>
            <NTabPane name="week" :tab="$t('common.job.week')">
              <CrontabWeek class="ml-2" :cron="crontabValueObj" :check="checkNumber" @update="updateCrontabValue" />
            </NTabPane>
            <NTabPane name="month" :tab="$t('common.job.month')">
              <CrontabMonth class="ml-2" :cron="crontabValueObj" :check="checkNumber" @update="updateCrontabValue" />
            </NTabPane>
            <NTabPane name="year" :tab="$t('common.job.year')">
              <CrontabYear class="ml-2" :cron="crontabValueObj" :check="checkNumber" @update="updateCrontabValue" />
            </NTabPane>
          </NTabs>
        </NCard>
        <!-- 时间表达式 -->
        <NCard class="mt-20px">
          <div class="popup-main">
            <div class="popup-result">
              <p class="title">{{ $t('common.job.timeExpression') }}</p>
              <table>
                <thead>
                  <th v-for="item of tabTitles" :key="item" width="40">
                    {{ item }}
                  </th>
                  <th>{{ $t('common.job.cronExpression') }}</th>
                </thead>
                <tbody>
                  <td>
                    <span>{{ crontabValueObj.second }}</span>
                  </td>
                  <td>
                    <span>{{ crontabValueObj.min }}</span>
                  </td>
                  <td>
                    <span>{{ crontabValueObj.hour }}</span>
                  </td>
                  <td>
                    <span>{{ crontabValueObj.day }}</span>
                  </td>
                  <td>
                    <span>{{ crontabValueObj.month }}</span>
                  </td>
                  <td>
                    <span>{{ crontabValueObj.week }}</span>
                  </td>
                  <td>
                    <span>{{ crontabValueObj.year }}</span>
                  </td>
                  <td>
                    <span>{{ crontabValueString }}</span>
                  </td>
                </tbody>
              </table>
            </div>
          </div>
        </NCard>
        <!-- 最近5次运行时间 -->
        <NCard class="mt-20px">
          <CrontabResult :ex="crontabValueString"></CrontabResult>
        </NCard>
      </NScrollbar>
      <template #footer>
        <NSpace justify="center" :size="16">
          <NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
          <NButton type="warning" @click="clearCron">{{ $t('common.reset') }}</NButton>
          <NButton type="primary" @click="submitFill">{{ $t('common.confirm') }}</NButton>
        </NSpace>
      </template>
    </NModal>
  </div>
</template>

<style scoped>
.popup-main {
  position: relative;
  margin: 10px auto;
  background: #fff;
  border-radius: 5px;
  font-size: 12px;
  overflow: hidden;
}

.popup-title {
  overflow: hidden;
  line-height: 34px;
  padding-top: 6px;
  background: #f2f2f2;
}

.popup-result {
  box-sizing: border-box;
  line-height: 24px;
  margin: 25px auto;
  padding: 15px 10px 10px;
  border: 1px solid #ccc;
  position: relative;
}

.popup-result .title {
  position: absolute;
  top: -28px;
  left: 50%;
  width: 140px;
  font-size: 14px;
  margin-left: -70px;
  text-align: center;
  line-height: 30px;
  background: #fff;
}

.popup-result table {
  text-align: center;
  width: 100%;
  margin: 0 auto;
}

.popup-result table span {
  display: block;
  width: 100%;
  font-family: arial;
  line-height: 30px;
  height: 30px;
  white-space: nowrap;
  overflow: hidden;
  border: 1px solid #e8e8e8;
}

.popup-result-scroll {
  font-size: 12px;
  line-height: 24px;
  height: 10em;
  overflow-y: auto;
}
</style>
